home *** CD-ROM | disk | FTP | other *** search
/ Freelog 115 / FreelogNo115-MaiJuin2013.iso / Internet / Filezilla Server / FileZilla_Server-0_9_41.exe / source / interface / AdminSocket.cpp next >
C/C++ Source or Header  |  2011-11-06  |  12KB  |  495 lines

  1. // FileZilla Server - a Windows ftp server
  2.  
  3. // Copyright (C) 2002-2004 - Tim Kosse <tim.kosse@gmx.de>
  4.  
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9.  
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14.  
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. // AdminSocket.cpp: Implementierung der Klasse CAdminSocket.
  20. //
  21. //////////////////////////////////////////////////////////////////////
  22.  
  23. #include "stdafx.h"
  24. #include "AdminSocket.h"
  25. #include "MainFrm.h"
  26. #include "../iputils.h"
  27. #include "../OptionTypes.h"
  28. #include "../platform.h"
  29. #include "../misc\md5.h"
  30.  
  31. //////////////////////////////////////////////////////////////////////
  32. // Konstruktion/Destruktion
  33. //////////////////////////////////////////////////////////////////////
  34.  
  35. #define BUFSIZE 4096
  36.  
  37. CAdminSocket::CAdminSocket(CMainFrame *pMainFrame)
  38. {
  39.     ASSERT(pMainFrame);
  40.     m_pMainFrame = pMainFrame;
  41.     m_pRecvBuffer = new unsigned char[BUFSIZE];
  42.     m_nRecvBufferLen = BUFSIZE;
  43.     m_nRecvBufferPos = 0;
  44.     m_nConnectionState = 0;
  45.     m_bClosed = FALSE;
  46. }
  47.  
  48. CAdminSocket::~CAdminSocket()
  49. {
  50.     delete [] m_pRecvBuffer;
  51.     
  52.     for (std::list<t_data>::iterator iter=m_SendBuffer.begin(); iter!=m_SendBuffer.end(); iter++)
  53.         delete [] iter->pData;
  54. }
  55.  
  56. void CAdminSocket::OnConnect(int nErrorCode)
  57. {
  58.     if (!nErrorCode)
  59.     {
  60.         if (!m_nConnectionState)
  61.         {
  62.             m_pMainFrame->ShowStatus(_T("Connected, waiting for authentication"), 0);
  63.             m_nConnectionState = 1;
  64.         }
  65.         m_pMainFrame->OnAdminInterfaceConnected();
  66.     }
  67.     else
  68.     {
  69.         m_pMainFrame->ShowStatus(_T("Error, could not connect to server"), 1);
  70.         Close();
  71.     }
  72. }
  73.  
  74. void CAdminSocket::OnReceive(int nErrorCode)
  75. {
  76.     if (nErrorCode)
  77.     {
  78.         m_pMainFrame->ShowStatus(_T("OnReceive failed, closing connection"), 1);
  79.         Close();
  80.         return;
  81.     }
  82.     
  83.     if (!m_nConnectionState)
  84.     {
  85.         m_pMainFrame->ShowStatus(_T("Connected, waiting for authentication"), 0);
  86.         m_nConnectionState = 1;
  87.     }
  88.  
  89.     int numread = Receive(m_pRecvBuffer + m_nRecvBufferPos, m_nRecvBufferLen - m_nRecvBufferPos);
  90.     if (numread > 0)
  91.     {
  92.         m_nRecvBufferPos += numread;
  93.         if (m_nRecvBufferLen-m_nRecvBufferPos < (BUFSIZE/4))
  94.         {
  95.             unsigned char *tmp = m_pRecvBuffer;
  96.             m_nRecvBufferLen += BUFSIZE;
  97.             m_pRecvBuffer = new unsigned char[m_nRecvBufferLen];
  98.             memcpy(m_pRecvBuffer, tmp, m_nRecvBufferPos);
  99.             delete [] tmp;
  100.         }
  101.     }
  102.     if (!numread)
  103.     {
  104.         Close();
  105.         return;
  106.     }
  107.     else if (numread == SOCKET_ERROR)
  108.     {
  109.         if (WSAGetLastError() != WSAEWOULDBLOCK)
  110.         {
  111.             Close();
  112.             return;
  113.         }
  114.     }
  115.     while (ParseRecvBuffer());
  116. }
  117.  
  118. void CAdminSocket::OnSend(int nErrorCode)
  119. {
  120.     if (nErrorCode)
  121.     {
  122.         Close();
  123.         return;
  124.     }
  125.     if (!m_nConnectionState)
  126.         return;
  127.  
  128.     while (!m_SendBuffer.empty())
  129.     {
  130.         t_data data = m_SendBuffer.front();
  131.         int nSent = Send(data.pData + data.dwOffset, data.dwLength - data.dwOffset);
  132.         if (!nSent)
  133.         {
  134.             Close();
  135.             return;
  136.         }
  137.         if (nSent == SOCKET_ERROR)
  138.         {
  139.             if (WSAGetLastError()!=WSAEWOULDBLOCK)
  140.                 Close();
  141.             return;
  142.         }
  143.         
  144.         if ((DWORD)nSent < (data.dwLength - data.dwOffset))
  145.             data.dwOffset += nSent;
  146.         else
  147.         {
  148.             m_SendBuffer.pop_front();
  149.             delete [] data.pData;
  150.         }
  151.     }
  152. }
  153.  
  154. void CAdminSocket::Close()
  155. {
  156.     if (m_nConnectionState)
  157.         m_pMainFrame->ShowStatus(_T("Connection to server closed."), 1);
  158.     m_nConnectionState = 0;
  159.     if (!m_bClosed)
  160.     {
  161.         m_bClosed = TRUE;
  162.         m_pMainFrame->PostMessage(WM_APP + 1, 0, 0);
  163.     }
  164. }
  165.  
  166. BOOL CAdminSocket::ParseRecvBuffer()
  167. {
  168.     DWORD len;
  169.     switch (m_nConnectionState)
  170.     {
  171.     case 1:
  172.         {
  173.             if (m_nRecvBufferPos<3)
  174.                 return FALSE;
  175.             if (m_pRecvBuffer[0] != 'F' || m_pRecvBuffer[1] != 'Z' || m_pRecvBuffer[2] != 'S')
  176.             {
  177.                 CString str;
  178.                 str.Format(_T("Protocol error: Unknown protocol identifier (0x%d 0x%d 0x%d). Most likely connected to the wrong port."), (int)m_pRecvBuffer[0], (int)m_pRecvBuffer[1], (int)m_pRecvBuffer[2]);
  179.                 m_pMainFrame->ShowStatus(str, 1);
  180.                 Close();
  181.                 return FALSE;
  182.             }
  183.             if (m_nRecvBufferPos < 5)
  184.                 return FALSE;
  185.             len = m_pRecvBuffer[3] * 256 + m_pRecvBuffer[4];
  186.             if (len != 4)
  187.             {
  188.                 CString str;
  189.                 str.Format(_T("Protocol error: Invalid server version length (%d)."), len);
  190.                 m_pMainFrame->ShowStatus(str, 1);
  191.                 Close();
  192.                 return FALSE;
  193.             }
  194.             if (m_nRecvBufferPos < 9)
  195.                 return FALSE;
  196.             
  197.             int version = (int)GET32(m_pRecvBuffer + 5);
  198.             if (version != SERVER_VERSION)
  199.             {
  200.                 CString str;
  201.                 str.Format(_T("Protocol warning: Server version mismatch: Server version is %d.%d.%d.%d, interface version is %d.%d.%d.%d"),
  202.                            (version >> 24) & 0xFF,
  203.                            (version >> 16) & 0xFF,
  204.                            (version >>  8) & 0xFF,
  205.                            (version >>  0) & 0xFF,
  206.                            (SERVER_VERSION >> 24) & 0xFF,
  207.                            (SERVER_VERSION >> 16) & 0xFF,
  208.                            (SERVER_VERSION >>  8) & 0xFF,
  209.                            (SERVER_VERSION >>  0) & 0xFF);
  210.                 m_pMainFrame->ShowStatus(str, 1);
  211.             }
  212.  
  213.             if (m_nRecvBufferPos<11)
  214.                 return FALSE;
  215.             len = m_pRecvBuffer[9] * 256 + m_pRecvBuffer[10];
  216.             if (len != 4)
  217.             {
  218.                 CString str;
  219.                 str.Format(_T("Protocol error: Invalid protocol version length (%d)."), len);
  220.                 m_pMainFrame->ShowStatus(str, 1);
  221.                 Close();
  222.                 return FALSE;
  223.             }
  224.             if (m_nRecvBufferPos<15)
  225.                 return FALSE;
  226.             version = (int)GET32(m_pRecvBuffer + 11);
  227.             if (version != PROTOCOL_VERSION)
  228.             {
  229.                 CString str;
  230.                 str.Format(_T("Protocol error: Protocol version mismatch: Server protocol version is %d.%d.%d.%d, interface protocol version is %d.%d.%d.%d"),
  231.                            (version >> 24) & 0xFF,
  232.                            (version >> 16) & 0xFF,
  233.                            (version >>  8) & 0xFF,
  234.                            (version >>  0) & 0xFF,
  235.                            (PROTOCOL_VERSION >> 24) & 0xFF,
  236.                            (PROTOCOL_VERSION >> 16) & 0xFF,
  237.                            (PROTOCOL_VERSION >>  8) & 0xFF,
  238.                            (PROTOCOL_VERSION >>  0) & 0xFF);
  239.                 m_pMainFrame->ShowStatus(str, 1);
  240.                 Close();
  241.                 return FALSE;
  242.             }
  243.  
  244.             memmove(m_pRecvBuffer, m_pRecvBuffer+15, m_nRecvBufferPos-15);
  245.             m_nRecvBufferPos-=15;
  246.             m_nConnectionState = 2;
  247.         }
  248.         break;
  249.     case 2:
  250.         if (m_nRecvBufferPos<5)
  251.             return FALSE;
  252.         if ((m_pRecvBuffer[0]&0x03) > 2)
  253.         {
  254.             CString str;
  255.             str.Format(_T("Protocol error: Unknown command type (%d), closing connection."), (int)(m_pRecvBuffer[0]&0x03));
  256.             m_pMainFrame->ShowStatus(str, 1);
  257.             Close();
  258.             return FALSE;
  259.         }
  260.         len = (int)GET32(m_pRecvBuffer + 1);
  261.         if (len + 5 <= m_nRecvBufferPos)
  262.         {
  263.             if ((m_pRecvBuffer[0]&0x03) == 0  &&  (m_pRecvBuffer[0]&0x7C)>>2 == 0)
  264.             {
  265.                 if (len<4)
  266.                 {
  267.                     m_pMainFrame->ShowStatus(_T("Invalid auth data"), 1);
  268.                     Close();
  269.                     return FALSE;
  270.                 }
  271.                 unsigned char *p = m_pRecvBuffer + 5;
  272.                 
  273.                 unsigned int noncelen1 = *p*256 + p[1];
  274.                 if ((noncelen1+2) > (len-2))
  275.                 {
  276.                     m_pMainFrame->ShowStatus(_T("Invalid auth data"), 1);
  277.                     Close();
  278.                     return FALSE;
  279.                 }
  280.                 
  281.                 unsigned int noncelen2 = p[2 + noncelen1]*256 + p[2 + noncelen1 +1];
  282.                 if ((noncelen1+noncelen2+4) > len)
  283.                 {
  284.                     m_pMainFrame->ShowStatus(_T("Invalid auth data"), 1);
  285.                     Close();
  286.                     return FALSE;
  287.                 }
  288.                 
  289.                 MD5 md5;
  290.                 if (noncelen1)
  291.                     md5.update(p+2, noncelen1);
  292.                 char* utf8 = ConvToNetwork(m_Password);
  293.                 if (!utf8)
  294.                 {
  295.                     m_pMainFrame->ShowStatus(_T("Can't convert password to UTF-8"), 1);
  296.                     Close();
  297.                     return FALSE;
  298.                 }
  299.                 md5.update((const unsigned char *)utf8, strlen(utf8));
  300.                 delete [] utf8;
  301.                 if (noncelen2)
  302.                     md5.update(p+noncelen1+4, noncelen2);
  303.                 md5.finalize();
  304.                 
  305.                 memmove(m_pRecvBuffer, m_pRecvBuffer+len+5, m_nRecvBufferPos-len-5);
  306.                 m_nRecvBufferPos-=len+5;
  307.                 
  308.                 unsigned char *digest = md5.raw_digest();
  309.                 SendCommand(0, digest, 16);
  310.                 delete [] digest;
  311.                 m_nConnectionState=3;
  312.                 return TRUE;
  313.             }
  314.             else if ((m_pRecvBuffer[0]&0x03) == 1  &&  (m_pRecvBuffer[0]&0x7C)>>2 == 0)
  315.             {
  316.                 m_nConnectionState=3;
  317.                 m_pMainFrame->ParseReply((m_pRecvBuffer[0]&0x7C)>>2, m_pRecvBuffer+5, len);
  318.             }
  319.             else
  320.             {
  321.                 CString str;
  322.                 str.Format(_T("Protocol error: Unknown command ID (%d), closing connection."), (int)(m_pRecvBuffer[0]&0x7C)>>2);
  323.                 m_pMainFrame->ShowStatus(str, 1);
  324.                 Close();
  325.                 return FALSE;
  326.             }
  327.             memmove(m_pRecvBuffer, m_pRecvBuffer+len+5, m_nRecvBufferPos-len-5);
  328.             m_nRecvBufferPos-=len+5;
  329.         }
  330.         break;
  331.     case 3:
  332.         if (m_nRecvBufferPos < 5)
  333.             return FALSE;
  334.         int nType = *m_pRecvBuffer & 0x03;
  335.         int nID = (*m_pRecvBuffer & 0x7C) >> 2;
  336.         if (nType > 2 || nType < 1)
  337.         {
  338.             CString str;
  339.             str.Format(_T("Protocol error: Unknown command type (%d), closing connection."), nType);
  340.             m_pMainFrame->ShowStatus(str, 1);
  341.             Close();
  342.             return FALSE;
  343.         }
  344.         else
  345.         {
  346.             len = (unsigned int)GET32(m_pRecvBuffer + 1);
  347.             if (len > 0xFFFFFF)
  348.             {
  349.                 CString str;
  350.                 str.Format(_T("Protocol error: Invalid data length (%u) for command (%d:%d)"), len, nType, nID);
  351.                 m_pMainFrame->ShowStatus(str, 1);
  352.                 Close();
  353.                 return FALSE;
  354.             }                
  355.             if (m_nRecvBufferPos < len+5)
  356.                 return FALSE;
  357.             else
  358.             {
  359.                 if (nType == 1)
  360.                     m_pMainFrame->ParseReply(nID, m_pRecvBuffer + 5, len);
  361.                 else if (nType == 2)
  362.                     m_pMainFrame->ParseStatus(nID, m_pRecvBuffer + 5, len);
  363.                 else
  364.                 {
  365.                     CString str;
  366.                     str.Format(_T("Protocol warning: Command type %d not implemented."), nType);
  367.                     m_pMainFrame->ShowStatus(str, 1);
  368.                 }
  369.                 
  370.                 memmove(m_pRecvBuffer, m_pRecvBuffer+len+5, m_nRecvBufferPos-len-5);
  371.                 m_nRecvBufferPos-=len+5;
  372.             }
  373.         }
  374.         break;
  375.     }
  376.     return TRUE;
  377. }
  378.  
  379. BOOL CAdminSocket::SendCommand(int nType)
  380. {
  381.     t_data data;
  382.     data.pData = new unsigned char[5];
  383.     data.pData[0] = nType << 2;
  384.     data.dwOffset = 0;
  385.     DWORD dwDataLength = 0;
  386.     memcpy(data.pData + 1, &dwDataLength, 4);
  387.  
  388.     data.dwLength = 5;
  389.  
  390.     m_SendBuffer.push_back(data);
  391.     
  392.     do 
  393.     {
  394.         data=m_SendBuffer.front();
  395.         int nSent = Send(data.pData+data.dwOffset, data.dwLength-data.dwOffset);
  396.         if (!nSent)
  397.         {
  398.             Close();
  399.             return FALSE;
  400.         }
  401.         if (nSent == SOCKET_ERROR)
  402.         {
  403.             if (WSAGetLastError()!=WSAEWOULDBLOCK)
  404.             {
  405.                 Close();
  406.                 return FALSE;
  407.             }
  408.             return TRUE;
  409.         }
  410.         
  411.         if ((DWORD)nSent < (data.dwLength-data.dwOffset))
  412.             data.dwOffset+=nSent;
  413.         else
  414.         {
  415.             m_SendBuffer.pop_front();
  416.             delete [] data.pData;
  417.         }
  418.     } while (!m_SendBuffer.empty());
  419.  
  420.     return TRUE;
  421. }
  422.  
  423. BOOL CAdminSocket::SendCommand(int nType, void *pData, int nDataLength)
  424. {
  425.     ASSERT((pData && nDataLength) || (!pData && !nDataLength));
  426.     
  427.     t_data data;
  428.     data.pData = new unsigned char[nDataLength+5];
  429.     data.pData[0] = nType << 2;
  430.     data.dwOffset = 0;
  431.     memcpy(data.pData + 1, &nDataLength, 4);
  432.     if (pData)
  433.         memcpy(data.pData+5, pData, nDataLength);
  434.  
  435.     data.dwLength = nDataLength + 5;
  436.  
  437.     m_SendBuffer.push_back(data);
  438.     
  439.     do 
  440.     {
  441.         data=m_SendBuffer.front();
  442.         int nSent = Send(data.pData+data.dwOffset, data.dwLength-data.dwOffset);
  443.         if (!nSent)
  444.         {
  445.             Close();
  446.             return FALSE;
  447.         }
  448.         if (nSent == SOCKET_ERROR)
  449.         {
  450.             if (WSAGetLastError()!=WSAEWOULDBLOCK)
  451.             {
  452.                 Close();
  453.                 return FALSE;
  454.             }
  455.             return TRUE;
  456.         }
  457.         
  458.         if ((DWORD)nSent < (data.dwLength-data.dwOffset))
  459.             data.dwOffset += nSent;
  460.         else
  461.         {
  462.             m_SendBuffer.pop_front();
  463.             delete [] data.pData;
  464.         }
  465.     } while (!m_SendBuffer.empty());
  466.  
  467.     return TRUE;
  468. }
  469.  
  470. BOOL CAdminSocket::IsConnected()
  471. {
  472.     return m_nConnectionState == 3;
  473. }
  474.  
  475. void CAdminSocket::OnClose(int nErrorCode)
  476. {
  477.     Close();
  478. }
  479.  
  480. void CAdminSocket::DoClose()
  481. {
  482.     m_bClosed = true;
  483.     Close();
  484. }
  485.  
  486. bool CAdminSocket::IsLocal()
  487. {
  488.     CString ip;
  489.     UINT port;
  490.     if (!GetPeerName(ip, port))
  491.         return false;
  492.  
  493.     return IsLocalhost(ip);
  494. }
  495.